﻿// KittyFeral PVE - HB Routine for FeralDruid 5.4 - By Neyia
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Styx.TreeSharp;
using Action = Styx.TreeSharp.Action;
using Styx.Pathing;
using System.Windows.Media;
using System.Threading;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;
using Bots.DungeonBuddy.Helpers;
using Styx.CommonBot.POI;

namespace KittyFeral
{
    public partial class Main : CombatRoutine
    {
        #region slog
        private void slog(string msg)
        {
            Logging.Write(msg);
        }

        private void slog(string format, params object[] args)
        {
            Logging.Write(format, args);
        }
        #endregion

        #region Buff Checks

        public bool buffExists(int Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(Buff);
                if (Results != null)
                    return true;
            }
            return false;
        }

        public double buffTimeLeft(int Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(Buff);
                if (Results != null)
                {
                    if (Results.TimeLeft.TotalMilliseconds > 0)
                        return Results.TimeLeft.TotalMilliseconds;
                }
            }
            return 0;
        }

        public bool buffExists(string Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraByName(Buff);
                if (Results != null)
                    return true;
            }
            return false;
        }

        public double buffTimeLeft(string Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraByName(Buff);
                if (Results != null)
                {
                    if (Results.TimeLeft.TotalMilliseconds > 0)
                        return Results.TimeLeft.TotalMilliseconds;
                }
            }
            return 0;
        }



        public uint buffStackCount(int Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(Buff);
                if (Results != null)
                    return Results.StackCount;
            }
            return 0;
        }
        public uint buffStackCount(string Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraByName(Buff);
                if (Results != null)
                    return Results.StackCount;
            }
            return 0;
        }
        #endregion

        #region Cache Checks
        public IEnumerable<WoWAura> cachedAuras = new List<WoWAura>();
        public IEnumerable<WoWAura> cachedTargetAuras = new List<WoWAura>();
        public void getCachedAuras()
        {
            if (Me.CurrentTarget != null)
                cachedTargetAuras = Me.CurrentTarget.GetAllAuras();
            cachedAuras = Me.GetAllAuras();
        }
        #endregion

        #region Cooldown Checks
        private Dictionary<WoWSpell, long> Cooldowns = new Dictionary<WoWSpell, long>();
        public TimeSpan cooldownLeft(int Spell)
        {
            SpellFindResults Results;
            if (SpellManager.FindSpell(Spell, out Results))
            {
                WoWSpell Result = Results.Override ?? Results.Original;
                if (Cooldowns.TryGetValue(Result, out lastUsed))
                {
                    if (DateTime.Now.Ticks < lastUsed)
                        return Result.CooldownTimeLeft;
                    return TimeSpan.MaxValue;
                }
            }
            return TimeSpan.MaxValue;
        }
        public TimeSpan cooldownLeft(string Spell)
        {
            SpellFindResults Results;
            if (SpellManager.FindSpell(Spell, out Results))
            {
                WoWSpell Result = Results.Override ?? Results.Original;
                if (Cooldowns.TryGetValue(Result, out lastUsed))
                {
                    if (DateTime.Now.Ticks < lastUsed)
                        return Result.CooldownTimeLeft;
                    return TimeSpan.MaxValue;
                }
            }
            return TimeSpan.MaxValue;
        }
        long lastUsed;
        public int lastCast;
        public bool onCooldown(int Spell)
        {
            SpellFindResults Results;
            if (SpellManager.FindSpell(Spell, out Results))
            {
                WoWSpell Result = Results.Override ?? Results.Original;
                if (Cooldowns.TryGetValue(Result, out lastUsed))
                {
                    if (DateTime.Now.Ticks < lastUsed)
                        return Result.Cooldown;
                    return false;
                }
            }
            return false;
        }
        public bool onCooldown(string Spell)
        {
            SpellFindResults Results;
            if (SpellManager.FindSpell(Spell, out Results))
            {
                WoWSpell Result = Results.Override ?? Results.Original;
                if (Cooldowns.TryGetValue(Result, out lastUsed))
                {
                    if (DateTime.Now.Ticks < lastUsed)
                        return Result.Cooldown;
                    return false;
                }
            }
            return false;
        }
        public TimeSpan spellCooldownLeft(int Spell, bool useTracker = false)
        {
            if (useTracker)
                return cooldownLeft(Spell);
            SpellFindResults results;
            if (SpellManager.FindSpell(Spell, out results))
            {
                if (results.Override != null)
                    return results.Override.CooldownTimeLeft;
                return results.Override.CooldownTimeLeft;
            }
            return TimeSpan.MaxValue;
        }
        public TimeSpan spellCooldownLeft(string Spell, bool useTracker = false)
        {
            if (useTracker)
                return cooldownLeft(Spell);
            SpellFindResults results;
            if (SpellManager.FindSpell(Spell, out results))
            {
                if (results.Override != null)
                    return results.Override.CooldownTimeLeft;
                return results.Override.CooldownTimeLeft;
            }
            return TimeSpan.MaxValue;
        }
        public bool spellOnCooldown(int Spell, bool useTracker = false)
        {
            if (useTracker)
                return !onCooldown(Spell);
            SpellFindResults results;
            if (SpellManager.FindSpell(Spell, out results))
                return results.Override != null ? results.Override.Cooldown : results.Original.Cooldown;
            return false;
        }
        public bool spellOnCooldown(string Spell, bool useTracker = false)
        {
            if (useTracker)
                return !onCooldown(Spell);
            SpellFindResults results;
            if (SpellManager.FindSpell(Spell, out results))
                return results.Override != null ? results.Override.Cooldown : results.Original.Cooldown;
            return false;
        }
        #endregion

        #region Debuff Checks

        public bool debuffExists(int Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a => a.SpellId == Debuff && a.CreatorGuid == Me.Guid);
                if (aura != null)
                {
                    return true;
                }
            }
            return false;
        }

        public double debuffTimeLeft(int Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a =>
                    a.SpellId == Debuff
                    && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
            return 0;
        }

        public uint debuffStackCount(int Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a =>
                    a.SpellId == Debuff
                    && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.StackCount;
            }
            return 0;
        }
        public bool debuffExists(string Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a => a.Name == Debuff && a.CreatorGuid == Me.Guid);
                if (aura != null)
                {
                    return true;
                }
            }
            return false;
        }

        public double debuffTimeLeft(string Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a =>
                    a.Name == Debuff
                    && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
            return 0;
        }

        public uint debuffStackCount(string Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a =>
                    a.Name == Debuff
                    && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.StackCount;
            }
            return 0;
        }
        #endregion

        #region Allowmovement
        [DllImport("user32.dll")]
        private static extern short GetAsyncKeyState(Keys vKey);

        public bool AllowFacing
        {
            get
            {
                if (SettingsExtraKittyFeral.myPrefs.DisableAutoFacing
                    && (Me.CurrentMap.IsRaid || Me.CurrentMap.IsDungeon || Me.CurrentMap.IsInstance))
                {
                    return false;
                }
                if ((GetAsyncKeyState(Keys.LButton) != 0
                    && GetAsyncKeyState(Keys.RButton) != 0) ||
                    GetAsyncKeyState(Keys.W) != 0 ||
                    GetAsyncKeyState(Keys.S) != 0 ||
                    GetAsyncKeyState(Keys.D) != 0 ||
                    GetAsyncKeyState(Keys.A) != 0)
                {
                    return false;
                }
                return SettingsExtraKittyFeral.myPrefs.AllowFacing;

            }
        }
        public bool AllowTargeting
        {
            get
            {
                if (SettingsExtraKittyFeral.myPrefs.DisableAutoTargeting
                    && (Me.CurrentMap.IsRaid || Me.CurrentMap.IsDungeon || Me.CurrentMap.IsInstance))
                {
                    return false;
                }
                if ((GetAsyncKeyState(Keys.LButton) != 0
                    && GetAsyncKeyState(Keys.RButton) != 0) ||
                    GetAsyncKeyState(Keys.W) != 0 ||
                    GetAsyncKeyState(Keys.S) != 0 ||
                    GetAsyncKeyState(Keys.D) != 0 ||
                    GetAsyncKeyState(Keys.A) != 0)
                {
                    return false;
                }
                return SettingsExtraKittyFeral.myPrefs.AllowTargeting;
            }
        }
        public bool AllowMovement
        {
            get
            {
                if (SettingsExtraKittyFeral.myPrefs.DisableAutoMovement
                    && (Me.CurrentMap.IsRaid || Me.CurrentMap.IsDungeon || Me.CurrentMap.IsInstance))
                {
                    return false;
                }
                if ((GetAsyncKeyState(Keys.LButton) != 0
                    && GetAsyncKeyState(Keys.RButton) != 0) ||
                    GetAsyncKeyState(Keys.W) != 0 ||
                    GetAsyncKeyState(Keys.S) != 0 ||
                    GetAsyncKeyState(Keys.D) != 0 ||
                    GetAsyncKeyState(Keys.A) != 0)
                {
                    return false;
                }


                return SettingsExtraKittyFeral.myPrefs.Movement;
            }
        }
        
        Composite CreateMovementBehavior()
        {
            return
                    new PrioritySelector(
                        new Decorator(ret => gotTarget && AllowMovement && (Me.CurrentTarget.Distance > myRange || !Me.CurrentTarget.InLineOfSight), new Action(ret => { Navigator.MoveTo(StyxWoW.Me.CurrentTarget.Location); ; return RunStatus.Failure; })),
                        new Decorator(ret => gotTarget && AllowMovement && Me.CurrentTarget.Distance <= myRange && Me.IsMoving,
                            new Action(ret => { Navigator.PlayerMover.MoveStop(); return RunStatus.Failure; }))
                );
        }
        float myRange
        {
            get
            {
                if (!SpellManager.HasSpell(CAT_FORM) && Me.Specialization == WoWSpec.None) { return 35; }
                if (SpellManager.HasSpell(CAT_FORM) && (Me.Specialization == WoWSpec.DruidFeral || Me.Specialization == WoWSpec.DruidGuardian)
                    && (Me.CurrentTarget != null && Me.CurrentTarget.IsPlayer)) { return 1.5f; }
                return 3.5f;
            }
        }
        Composite GoBackwards()
        {
            return
                new Action(delegate
                {

                    WoWMovement.Move(WoWMovement.MovementDirection.Backwards);
                    while (gotTarget && Me.CurrentTarget.IsAlive && Me.CurrentTarget.Distance <= 10)
                    {
                        break;
                    }
                    WoWMovement.MoveStop();
                    return RunStatus.Failure;
                });
        }
        #endregion

        #region hastebuffs
        public string BLOODLUST = "Bloodlust";
        public string TIME_WARP = "Time Warp";
        public string HEROISM = "Heroism";
        public string DRUMS_OF_RAGE = "Drums of Rage";
        public bool NotHaveHasteBuffs()
        {
            return !buffExists(BLOODLUST, Me)
                && !buffExists(TIME_WARP, Me)
                && !buffExists(HEROISM, Me)
                && !buffExists(DRUMS_OF_RAGE, Me);
        }
        #endregion

        #region statsbuffs
        public string MOTW = "Mark of the Wild";
        public string LEGACY_OF_THE_EMPEOR = "Legacy of the Emperor";
        public string BLESSING_OF_KINGS = "Blessing of Kings";
        public bool NotHaveStatsBuffs()
        {
            return !buffExists(MOTW, Me)
                && !buffExists(LEGACY_OF_THE_EMPEOR, Me)
                && !buffExists(BLESSING_OF_KINGS, Me);
        }
        #endregion

        #region rooted
        Composite RemoveRooted()
        {
            return
                    new Action(ret =>
                    {
                        if (Me.Shapeshift == ShapeshiftForm.Cat)
                        {
                            Lua.DoString("RunMacroText(\"/Cast !Cat Form\")");
                        }
                        if (Me.Shapeshift == ShapeshiftForm.Bear)
                        {
                            Lua.DoString("RunMacroText(\"/Cast !Bear Form\")");
                        }
                        return RunStatus.Failure;
                    });
        }
        #endregion

        #region class milli seconds
        static class CurrentMillis
        {
            private static readonly DateTime Jan1St1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            /// <summary>Get extra long current timestamp</summary>
            public static long Millis { get { return (long)((DateTime.UtcNow - Jan1St1970).TotalMilliseconds); } }
        }
        #endregion

        #region flask buffs
        public int Flask_OF_THE_EARTH_BUFF = 105694;
        public int Flask_OF_THE_WARM_SUN_BUFF = 105691;
        public int FLASK_OF_WINTERS_BITE_BUFF = 105696;
        public int FLASK_OF_FALLING_LEAVES_BUFF = 105693;
        public int FLASK_OF_SPRING_BLOSSOMS_BUFF = 105698;

        public bool NotHaveFlaskBuff
        {
            get
            {
                return !buffExists(Flask_OF_THE_EARTH_BUFF, Me)
                    && !buffExists(Flask_OF_THE_WARM_SUN_BUFF, Me)
                    && !buffExists(FLASK_OF_WINTERS_BITE_BUFF, Me)
                    && !buffExists(FLASK_OF_FALLING_LEAVES_BUFF, Me)
                    && !buffExists(FLASK_OF_SPRING_BLOSSOMS_BUFF, Me);
            }
        }
        #endregion

        #region FindTarget
        WoWUnit FindTarget()
        {
                    WoWUnit myTarget = ObjectManager.GetObjectsOfType<WoWUnit>(true, false).Where(u => ValidUnit(u)
                        && u.DistanceSqr <= 40 * 40
                        && !Blacklist.Contains(u, BlacklistFlags.All))
                        .OrderBy(u => u.IsPlayer)
                        .ThenBy(u => u.Distance)
                        .FirstOrDefault();
                    if (myTarget != null)
                    {
                        Logging.Write(Colors.PaleGreen, "Found new Target " + myTarget.Name);
                        myTarget.Target();
                        return myTarget;
                    }
                    return null;
        }
        #endregion

        #region whatspelliscasting
        public bool NeedInterrupt
        {
            get
            {
                if (Me.CurrentTarget != null && Me.CurrentTarget.IsCasting && AllowMovement)
                {
                    string whatSpellIsCasting = Me.CurrentTarget.CastingSpell.ToString();
                    switch (whatSpellIsCasting)
                    {
                        case "Blazing Cleave":
                            return true;
                        default:
                            return false;
                    }
                }
                return false;
            }
        }

        public string CheckSpellCast()
        {
            //var theSpellCast = Lua.GetReturnVal<string>(String.Format ("return spell=UnitCastingInfo(" + Me.CurrentTarget + ")"), 0);

            string theSpellcast = Me.CurrentTarget.CastingSpell.ToString();
            return theSpellcast;
        }

        #endregion

        #region facing
        Composite FaceMyTarget()
        {
            return
                new Decorator(ret => Me.CurrentTarget != null && AllowFacing && !Me.IsSafelyFacing(Me.CurrentTarget) && !Me.IsMoving,
                    new Action(ret =>
                    {
                        Me.CurrentTarget.Face();
                        return RunStatus.Failure;
                    }));
        }
        #endregion

        #region valid units
        public bool ValidUnit(WoWUnit p)
        {
            if (p == null || !p.IsValid)
                return false;

            // Ignore shit we can't select
            if (!p.CanSelect)
            {
                return false;
            }

            // Ignore shit we can't attack
            if (!p.Attackable)
            {
                return false;
            }

            // Duh
            if (p.IsDead)
            {
                return false;
            }

            // check for enemy players here as friendly only seems to work on npc's
            if (p.IsPlayer)
            {
                WoWPlayer pp = p.ToPlayer();
                if (pp.IsHorde == StyxWoW.Me.IsHorde)
                {
                    return false;
                }

                if (pp.Guid == StyxWoW.Me.CurrentTargetGuid && CanAttackCurrentTarget)
                {
                    return false;
                }

                return true;
            }

            // Ignore friendlies!
            if (p.IsFriendly)
            {
                return false;
            }
            // If it is a pet/minion/totem, lets find the root of ownership chain
            WoWPlayer pOwner = GetPlayerParent(p);

            // ignore if owner is player, alive, and not blacklisted then ignore (since killing owner kills it)
            // .. following .IsMe check to prevent treating quest mob summoned by us that we need to kill as invalid 
            if (pOwner != null && pOwner.IsAlive && !pOwner.IsMe)
            {
                if (!ValidUnit(pOwner))
                {
                    return false;
                }
                if (!Blacklist.Contains(pOwner, BlacklistFlags.Combat))
                {
                    return false;
                }
                if (!StyxWoW.Me.IsPvPFlagged)
                {
                    return false;
                }
            }

            // And ignore critters (except for those ferocious ones) /non-combat pets
            if (p.IsNonCombatPet)
            {
                return false;
            }

            // And ignore critters (except for those ferocious ones) /non-combat pets
            if (p.IsCritter && p.ThreatInfo.ThreatValue == 0 && !p.IsTargetingMyRaidMember)
            {
                return false;
            }
            /*
                        if (p.CreatedByUnitGuid != 0 || p.SummonedByUnitGuid != 0)
                            return false;
            */
            return true;
        }

        public WoWPlayer GetPlayerParent(WoWUnit unit)
        {
            // If it is a pet/minion/totem, lets find the root of ownership chain
            WoWUnit pOwner = unit;
            while (true)
            {
                if (pOwner.OwnedByUnit != null)
                    pOwner = pOwner.OwnedByRoot;
                else if (pOwner.CreatedByUnit != null)
                    pOwner = pOwner.CreatedByUnit;
                else if (pOwner.SummonedByUnit != null)
                    pOwner = pOwner.SummonedByUnit;
                else
                    break;
            }

            if (unit != pOwner && pOwner.IsPlayer)
                return pOwner as WoWPlayer;

            return null;
        }
        public bool CanAttackCurrentTarget
        {
            get
            {
                if (StyxWoW.Me.CurrentTarget == null)
                    return false;

                return Lua.GetReturnVal<bool>("return UnitCanAttack(\"player\",\"target\")", 0);
            }
        }
        #endregion

        #region crowdcontrol
        public bool BreakRooted
        {
            get
            {
                if (Me.Specialization == WoWSpec.DruidGuardian && CRSettingsBear.myPrefs.AutoShapeShift)
                {
                    return true;
                }
                if (Me.Specialization == WoWSpec.DruidFeral && CRSettingsCat.myPrefs.AutoShapeShift)
                {
                    return true;
                }
                return false;
            }
        }
        public bool IsCrowdControlledTarget(WoWUnit unit)
        {
            Dictionary<string, WoWAura>.ValueCollection auras = unit.Auras.Values;

            return unit.Fleeing
                || HasAuraWithEffect(unit,
                        WoWApplyAuraType.ModConfuse,
                        WoWApplyAuraType.ModCharm,
                        WoWApplyAuraType.ModFear,
                        WoWApplyAuraType.ModPossess);
        }

        public bool IsCrowdControlledPlayer(WoWUnit unit)
        {
            Dictionary<string, WoWAura>.ValueCollection auras = unit.Auras.Values;

            return unit.Rooted
                || HasAuraWithEffect(unit,
                        WoWApplyAuraType.ModRoot);
        }

        // this one optimized for single applytype lookup
        public bool HasAuraWithEffect(WoWUnit unit, WoWApplyAuraType applyType)
        {
            return unit.Auras.Values.Any(a => a.Spell != null && a.Spell.SpellEffects.Any(se => applyType == se.AuraType));
        }

        public static bool HasAuraWithEffect(WoWUnit unit, params WoWApplyAuraType[] applyType)
        {
            var hashes = new HashSet<WoWApplyAuraType>(applyType);
            return unit.Auras.Values.Any(a => a.Spell != null && a.Spell.SpellEffects.Any(se => hashes.Contains(se.AuraType)));
        }
        #endregion

        #region need go backwards
        public bool NeedGoBackwards
        {
            get
            {
                if (Me.CurrentTarget != null 
                    && Me.CurrentTarget.IsAlive 
                    && AllowMovement 
                    && Me.CurrentTarget.Name == "Burning Berserker" 
                    && (Me.CurrentTarget.IsCasting 
                    && Me.CurrentTarget.CastingSpell.ToString() == "Blazing Cleave"))
                {
                    return true;
                }
                return false;
            }
        }
        #endregion

        #region use items
        Composite Trinket1Cat()
        {
            return
                new Decorator(ret => gotTarget && Me.Combat && CRSettingsCat.myPrefs.AutoTrinket1 && (Me.CurrentTarget != null && Me.CurrentTarget.IsWithinMeleeRange),
                    new Action(ret =>
                    {
                        var firstTrinket = StyxWoW.Me.Inventory.Equipped.Trinket1;

                        if (CRSettingsCat.myPrefs.trinket1manapercent > 0
                            && Me.ManaPercent <= CRSettingsCat.myPrefs.trinket1manapercent
                            && firstTrinket != null
                            && CanUseEquippedItem(firstTrinket))
                        {
                            firstTrinket.Use();
                            return RunStatus.Success;
                        }
                        if (CRSettingsCat.myPrefs.trinket1hppercent > 0
                            && Me.ManaPercent <= CRSettingsCat.myPrefs.trinket1hppercent
                            && firstTrinket != null
                            && CanUseEquippedItem(firstTrinket))
                        {
                            firstTrinket.Use();
                            return RunStatus.Success;
                        }
                        if (CRSettingsCat.myPrefs.trinket1crowdcontrolled
                            && IsCrowdControlledPlayer(Me)
                            && firstTrinket != null
                            && CanUseEquippedItem(firstTrinket))
                        {
                            firstTrinket.Use();
                            return RunStatus.Success;
                        }
                        if (CRSettingsCat.myPrefs.trinket1dpsboost
                            && firstTrinket != null
                            && CanUseEquippedItem(firstTrinket))
                        {
                            firstTrinket.Use();
                            return RunStatus.Success;
                        }
                        return RunStatus.Failure;
                    }));
        }
        Composite Trinket2Cat()
        {
            return
                new Decorator(ret => gotTarget && Me.Combat && CRSettingsCat.myPrefs.AutoTrinket2 && (Me.CurrentTarget != null && Me.CurrentTarget.IsWithinMeleeRange),
                    new Action(ret =>
                    {
                        var secondTrinket = StyxWoW.Me.Inventory.Equipped.Trinket2;

                        if (CRSettingsCat.myPrefs.trinket2manapercent > 0
                            && Me.ManaPercent <= CRSettingsCat.myPrefs.trinket2manapercent
                            && secondTrinket != null
                            && CanUseEquippedItem(secondTrinket))
                        {
                            secondTrinket.Use();
                            return RunStatus.Success;
                        }
                        if (CRSettingsCat.myPrefs.trinket2hppercent > 0
                            && Me.ManaPercent <= CRSettingsCat.myPrefs.trinket2hppercent
                            && secondTrinket != null
                            && CanUseEquippedItem(secondTrinket))
                        {
                            secondTrinket.Use();
                            return RunStatus.Success;
                        }
                        if (CRSettingsCat.myPrefs.trinket2crowdcontrolled
                            && IsCrowdControlledPlayer(Me)
                            && secondTrinket != null
                            && CanUseEquippedItem(secondTrinket))
                        {
                            secondTrinket.Use();
                            return RunStatus.Success;
                        }
                        if (CRSettingsCat.myPrefs.trinket2dpsboost
                            && secondTrinket != null
                            && CanUseEquippedItem(secondTrinket))
                        {
                            secondTrinket.Use();
                            return RunStatus.Success;
                        }
                        return RunStatus.Failure;
                    }));
        }
        Composite Trinket1Bear()
        {
            return
                new Decorator(ret => gotTarget && Me.Combat && CRSettingsBear.myPrefs.AutoTrinket1 && (Me.CurrentTarget != null && Me.CurrentTarget.IsWithinMeleeRange),
                    new Action(ret =>
                    {
                        var firstTrinket = StyxWoW.Me.Inventory.Equipped.Trinket1;

                        if (CRSettingsBear.myPrefs.trinket1manapercent > 0
                            && Me.ManaPercent <= CRSettingsBear.myPrefs.trinket1manapercent
                            && firstTrinket != null
                            && CanUseEquippedItem(firstTrinket))
                        {
                            firstTrinket.Use();
                            return RunStatus.Success;
                        }
                        if (CRSettingsBear.myPrefs.trinket1hppercent > 0
                            && Me.ManaPercent <= CRSettingsBear.myPrefs.trinket1hppercent
                            && firstTrinket != null
                            && CanUseEquippedItem(firstTrinket))
                        {
                            firstTrinket.Use();
                            return RunStatus.Success;
                        }
                        if (CRSettingsBear.myPrefs.trinket1crowdcontrolled
                            && IsCrowdControlledPlayer(Me)
                            && firstTrinket != null
                            && CanUseEquippedItem(firstTrinket))
                        {
                            firstTrinket.Use();
                            return RunStatus.Success;
                        }
                        if (CRSettingsBear.myPrefs.trinket1dpsboost
                            && firstTrinket != null
                            && CanUseEquippedItem(firstTrinket))
                        {
                            firstTrinket.Use();
                            return RunStatus.Success;
                        }
                        return RunStatus.Failure;
                    }));
        }
        Composite Trinket2Bear()
        {
            return
                new Decorator(ret => gotTarget && Me.Combat && CRSettingsBear.myPrefs.AutoTrinket2 && (Me.CurrentTarget != null && Me.CurrentTarget.IsWithinMeleeRange),
                    new Action(ret =>
                    {
                        var secondTrinket = StyxWoW.Me.Inventory.Equipped.Trinket2;

                        if (CRSettingsBear.myPrefs.trinket2manapercent > 0
                            && Me.ManaPercent <= CRSettingsBear.myPrefs.trinket2manapercent
                            && secondTrinket != null
                            && CanUseEquippedItem(secondTrinket))
                        {
                            secondTrinket.Use();
                            return RunStatus.Success;
                        }
                        if (CRSettingsBear.myPrefs.trinket2hppercent > 0
                            && Me.ManaPercent <= CRSettingsBear.myPrefs.trinket2hppercent
                            && secondTrinket != null
                            && CanUseEquippedItem(secondTrinket))
                        {
                            secondTrinket.Use();
                            return RunStatus.Success;
                        }
                        if (CRSettingsBear.myPrefs.trinket2crowdcontrolled
                            && IsCrowdControlledPlayer(Me)
                            && secondTrinket != null
                            && CanUseEquippedItem(secondTrinket))
                        {
                            secondTrinket.Use();
                            return RunStatus.Success;
                        }
                        if (CRSettingsBear.myPrefs.trinket2dpsboost
                            && secondTrinket != null
                            && CanUseEquippedItem(secondTrinket))
                        {
                            secondTrinket.Use();
                            return RunStatus.Success;
                        }
                        return RunStatus.Failure;
                    }));
        }
        Composite HealthstoneCat()
        {
            return new Decorator(ret => Me.Combat && Me.HealthPercent <= CRSettingsCat.myPrefs.useHealthstone,
                new Action(ret =>
                {
                    var hstone = ObjectManager.GetObjectsOfType<WoWItem>().FirstOrDefault(item => item.Entry == 5512);
                    if (hstone != null && hstone.Usable)
                    {
                        hstone.Use();
                        Logging.Write("Using Healthstone");
                        return RunStatus.Success;
                    }
                    return RunStatus.Failure;
                }));
        }
        Composite HealthstoneBear()
        {
            return new Decorator(ret => Me.Combat && Me.HealthPercent <= CRSettingsBear.myPrefs.useHealthstone,
                new Action(ret =>
                {
                    var hstone = ObjectManager.GetObjectsOfType<WoWItem>().FirstOrDefault(item => item.Entry == 5512);
                    if (hstone != null && hstone.Usable)
                    {
                        hstone.Use();
                        Logging.Write("Using Healthstone");
                        return RunStatus.Success;
                    }
                    return RunStatus.Failure;
                }));
        }
        Composite AlchemyFlask()
        {
            return new Decorator(
                new Action(ret =>
                {
                    var alchflask = ObjectManager.GetObjectsOfType<WoWItem>().FirstOrDefault(item => item.Entry == 75525);
                    if (alchflask != null && alchflask.Usable && alchflask.Cooldown <= 0)
                    {
                        alchflask.Use();
                        return RunStatus.Success;
                    }
                    return RunStatus.Failure;
                }));
        }
        Composite CrystalOfInsanity()
        {
            return new Action(ret =>
            {
                var crystal = ObjectManager.GetObjectsOfType<WoWItem>().FirstOrDefault(item => item.Entry == 86569);
                if (crystal != null && crystal.Usable && crystal.Cooldown <= 0)
                {
                    crystal.Use();
                    return RunStatus.Success;
                }
                return RunStatus.Failure;
            });
        }
        #endregion

        #region ingame
        private static bool IsInGame
        {
            get { return Styx.StyxWoW.IsInGame; }
        }
        #endregion
    }
}
